import PropTypes from '@zh/common-utils/prop-types'
import ArrayUtil from '@zh/common-utils/utils/array'
import storage from '@zh/common-utils/utils/storage'
import { store } from '../store.js'

export default {
  name: 'Menu',
  props: {
    menuList: PropTypes.array.require(),
    theme: PropTypes.string.def('dark'),
    mode: PropTypes.string.def('inline'),
    collapsed: PropTypes.bool.def(false)
  },
  data () {
    return {
      menuMap: {},
      menuIdMap: {},
      openKeys: [],
      selectedKeys: [],
      tempOpenKeys: []
    }
  },
  computed: {
    rootSubmenuKeys (vm) {
      const keys = []
      vm.menuList.forEach(function (item) {
        return keys.push(item.meta.id)
      })
      return keys
    },
    computedNavPosition () {
      return this.$store.getTheme('navPosition')
    }
  },
  watch: {
    collapsed (value) {
      if (value) {
        this.tempOpenKeys = this.openKeys
        this.openKeys = []
      } else {
        this.openKeys = this.tempOpenKeys
      }
    },
    $route: {
      deep: true,
      immediate: true,
      handler (n, o) {
        // if (n.meta.dynamic && o) {
        //   n.query.from = encodeURIComponent(o.meta?.key || o.path)
        // }
        if (Object.keys(this.menuMap).length == 0) {
          this.menuList.map(menuItem => {
            menuToMap(menuItem, this.menuMap)
          })
        }

        this.handleRouteChange()
      }
    }
  },
  created () {
    store.reloadMenu = () => this.$forceUpdate()
  },
  methods: {
    handleRouteChange () {
      let key = this.$route.meta.key || this.$route.path,
        menuItem = this.menuMap[key]

      if (this.$route.meta?.weak && this.$route.meta?.hidden === true) {
        // 如果当前菜单为隐藏菜单并且路由与菜单弱关联，则不高亮菜单
        return
      }

      if (!menuItem) {
        key = storage.get('menu')
        menuItem = this.menuMap[storage.get('menu')]
      }

      if (menuItem) {

        const parents = [...ArrayUtil.getParents(menuItem, false)]

        // 当前路由如果类型为功能，则当前高亮菜单为上级节点
        this.selectedKeys = [menuItem.meta?.hidden ? parents.length > 0 ? parents[0].id : key : key]
        menuItem.meta.hidden && parents.shift()

        if (this.$store.getTheme('navPosition') !== 'top') {
          this.openKeys = parents.map(p => p.meta?.key || p.path)
        }

        storage.set('menu', this.selectedKeys[0])
      }
    }
  },
  render (h) {
    const me = this
    return h('a-menu', {
      props: {
        openKeys: this.openKeys,
        selectedKeys: this.selectedKeys,
        theme: this.theme,
        mode: this.mode
      },
      on: {
        select (menuItem) {
          // 点击菜单
          const menu = me.menuMap[menuItem.key], target = me.menuMap[menuItem.key].meta.target
          if (target != '_blank') {
            me.selectedKeys = menuItem.selectedKeys
            me.$emit('select', menu, me.menuMap)
          } else if (menu.path.startsWith('http://') || menu.path.startsWith('https://')) {
            const token = storage.getToken().value
            const path = menu.path + (menu.path.indexOf('?') == -1 ? '?' : '&') + `token=${token} `
            window.open(path)
          } else {
            window.open(me.$router.resolve({
              path: menu.path,
              query: menu.query
            }).href, '_blank')
          }
        },
        openChange (openKeys) {
          // 在水平模式下时，不再执行后续
          if (me.mode === 'horizontal') {
            me.openKeys = openKeys
            return
          }
          const latestOpenKey = openKeys.find(function (key) {
            return !me.openKeys.includes(key)
          })
          if (!me.rootSubmenuKeys.includes(latestOpenKey)) {
            me.openKeys = openKeys
          } else {
            me.openKeys = latestOpenKey ? [latestOpenKey] : []
          }
        }
      }
    }, [this.menuList.map(menu => renderMenuItem(h, menu))])
  }
}

function matched (menu, menuMap) {

}

function menuToMap (menu, map) {
  map[menu.meta?.key || menu.path] = menu
  menu.children && menu.children.forEach(subMenu => {
    menuToMap(subMenu, map)
  })
}

function renderMenuItem (h, menuItem) {
  if (menuItem.meta.hidden) {
    return null
  }
  if (menuItem.children) {
    const notHideNode = menuItem.children.find(child => !child.meta.hidden)
    if (notHideNode) {
      return renderSubMenu(h, menuItem)
    }
  }
  return h('a-menu-item', {
    key: menuItem.meta?.key || menuItem.path
  }, [
    menuItem.parentId == '0' && renderIcon(h, menuItem.meta.icon),
    renderTitle(h, menuItem.meta.title),
    renderBadge(h, menuItem.meta.badge)
  ])
}

function renderSubMenu (h, menuItem) {
  return h('a-sub-menu', {
    key: menuItem.meta.id,
    attrs: {
      title: h('span', [
        menuItem.parentId == '0' && renderIcon(h, menuItem.meta.icon),
        renderTitle(h, menuItem.meta.title),
        renderBadge(h, menuItem.meta.badge)
      ])
    }
  }, [menuItem.children.map(menu => renderMenuItem(h, menu))])
}

function renderIcon (h, icon) {
  if (icon === undefined || icon === 'none' || icon === null || icon === '') {
    return null
  }
  let props = {}
  typeof icon === 'object' ? props.component = icon : props.type = icon
  return h('a-icon', {
    props: props
  })
}

function renderTitle (h, title) {
  return h('span', [title])
}

function renderBadge (h, badge) {
  if (badge === undefined || badge === 'none' || badge === null || badge === '') {
    return null
  }
  if (typeof badge === 'boolean') {
    badge = { dot: badge }
  } else if (typeof badge === 'number' || typeof badge === 'string') {
    badge = { count: parseInt(badge) }
  }
  return badge
    ? h('a-badge', {
      attrs: {
        count: badge.count,
        dot: !!badge.dot,
        style: badge.dot ? '' : 'margin-left: 4px; margin-top: -4px;'
      }
    })
    : null
}